/*
  Name: level.CPP
  Copyright: Nou
  Author: Julian Williams
  Date: 4/18/10
  Description: Handels the level routines that are used to 
				control the envirnment 
*/


#include <iostream>
#include <fstream>

#include <SFML/Graphics.hpp> // Include the allegro header file.


#include "app.h"
#include "SFMLMappy.h"
#include "levels.h"
#include "iniparser.h"
#include "Camera.h"
#include "text.h"
#include "player.h"



using namespace std;

//define Map instance
c_Map Map;

c_Map::c_Map()
{
	current_map = 0;
}


/* Set's up the Map list */
/*************************/
bool c_Map::Setup_List(string cfg_file)
{
    cout << "****************************************************************\n";
	cout << "-Setting Map list up-" << endl;

	//Get level directory
	string List_loc(cfg_file);
	string map_name;


	//Open up the list List file
	ifstream List_file(List_loc.c_str());
    
	//if file isn't open, return false
	if(!List_file.is_open()) { return false; }

	do 
	{
		//Read in every line
		getline( List_file, map_name);

		if(map_name == "") { break; }

		List.push_back(map_name);
		cout << "Level '" << map_name <<"' added" << endl;

	} while( !List_file.eof() );

	//save the number of maps
	max_count = List.size();

	//Close file
	List_file.close();

	cout << "Level Setup complete, total map count: " << max_count << " Recorded. \n";
	cout << "****************************************************************\n\n";
	return true;
}//end ov function



/* Effects Manager */
/******************
void c_Map::effects_manager()
{
     /* I should move this 
         switch(FX)
         {
                case FX_RAIN:
                     FX_rain(get_buffer(), 0);
                     
                    break;
         }
}//end ov function
*/





/* Getter's/Setter's for map number */
/************************************/
void c_Map::Set_Current(int mapNum)
{
     current_map = mapNum;
}//EoF


int c_Map::Get_Current()
{
    return current_map;
}//EoF







/* Read in info about the map */
/******************************/
/*Read level stats from file and save it to level Object*/     
bool c_Map::Get_Info(string datafile_loc)
{  
    
     string bg_loc("resources/backgrounds/");
     string music_loc("resources/soundtrack/");
     
   
     	dictionary	*	ini = iniparser_load(datafile_loc.c_str());

		if (ini==NULL)
		{
			cout << "Couldn't load configuration file from, " << datafile_loc.c_str() << "  sorry :0 \n";
			return false;
		}
	

		//Get gravity
		 savedGravity = iniparser_getint(ini, "Info:gravity", 300);
		 cout << "Gravity: " << savedGravity << endl;

		

//Load background
/****************/
		 int background_count = iniparser_getint(ini, "Backgrounds:background_count", 0);
 
		 for(int i = 0; i < background_count; i++)
		 {
			 //Create the name to look up
			 string getName = Text::Create_TextWithArgs("Backgrounds:b_%d", i);
			 string getSpeed = Text::Create_TextWithArgs("Backgrounds:speed_%d", i);

		//	 string getNamem = string("Backgrounds:b_0");

			 cout << getSpeed << ", " << getName << endl;

			 //Load Background name, and scroll speed
     		 string bg_name = iniparser_getstring(ini, getName.c_str(), "default.png");
			 double scroll_speed =  iniparser_getdouble(ini, getSpeed.c_str(), 0.5);

			 //if loading has failed, skip it, and don't load it
			 if(bg_name == "default.png") { continue; }


		//Add Name to its location
			string nbg_loc = bg_loc + bg_name;
			cout << nbg_loc << endl;

			//create new parallax background object
			Parallax p(scroll_speed, nbg_loc);

			//add to background list
			Backgrounds.push_back(p);
		 }//end ov for 



	 // Backgrounds[0].Load( bg_loc );
	 // Backgrounds[0].Set_ScrollSpeed( 0.5 );

	 //Load Image
    // Images.background = load_bitmap(bg_loc, NULL);//Load background

	
     
     
     
//Load Music
/************/
     string music_name = iniparser_getstring(ini, "Info:music", "<none>");
     //Add name to its location
	 music_loc += music_name;

     
     if(music_name == "<none>")
     {
                 cout << "No music found at - " << music_loc << endl;
     }else{
           //Load Music
		 cout << "Loading Music from: " << music_loc << endl;

		 if(!App::getInstance().Music.OpenFromFile(music_loc))
		 {
				 cout << "Couldn't Open: " << music_loc << endl;
				 return false;
		 }

		 App::getInstance().Music.SetVolume(30.0f);
		 App::getInstance().Music.SetLoop(true);
	

		 App::getInstance().Music.Play();

		 /*
                   SND.music = FSOUND_Stream_Open(music_loc, FSOUND_LOOP_NORMAL, 0, 0); 
                   SND.check(SND.music); 
                   
                   //Play music
                   FSOUND_Stream_Play(0,SND.music);
                   FSOUND_SetVolume (0, 80);
				   */
				   
     }
     

//load Map FX's
	 /*
     char *fx_type = ustrdup(get_config_string("Info", "special_effects", "<none>"));
     
     if(      strcmp(fx_type, "FX_RAIN") == 0) 
     {
               FX = FX_RAIN;
               
     }else if(strcmp(fx_type, "FX_SNOW") == 0)
     {
               FX = FX_SNOW;
               
     }else if(strcmp(fx_type, "FX_FOG") == 0)
     {
               FX = FX_FOG;
               
     }else if(strcmp(fx_type, "FX_DARK") == 0)
     {
               FX = FX_DARK;
               
     }else{
               FX = FX_NONE;
     }    
	 */
	return true;
}//End ov function





/* Base Map Loader */
/*******************/
void c_Map::Load()
{

		Backgrounds.reserve(2);

      
      string mapFmp_location;
      string mapInfo_location;
      
      string map_dir = string("resources/maps/") + List[current_map] + string("/");
      
      
      //fade out
     // screen_fade_out(15);
      
      
      if(current_map > max_count) { current_map = 0; }    
      
	  //Set up locations of files to read into the engine
	  mapFmp_location  = map_dir + string("stage.fmp");
	  mapInfo_location = map_dir + string("info.txt");

	  //Print out location to console
      cout << ">Loading Level[" << current_map << "] - '" << List[current_map] <<  "' From location - " << mapFmp_location << endl;
      
      
      if(mapFmp_location == "data/maps/(null)/stage.fmp") 
      {
                         cout << "\nCannot load map " << List[current_map];
                          
                        //  Game_State = MENU;
      }else{
    

			//Load data
			 Get_Info(mapInfo_location);
     
			 //Load Map 
			if (!LoadMap(mapFmp_location.c_str())) 
			 {
				 cout << "\nFAILED to load map....sorry :0" << endl;

               //   g_error("Sorry, End of the Demo :( \n Please, help me pay for school so I can do this for a living!!!");
			 }else{
					cout << "-Current Map: " << current_map << "\n\n";
			 }	
      
      
			 //Convert our variables to mappy's
			 size.x = GetMapWidth();
		  	 size.y = GetMapHeight();
      
			 tile_dimensions.x = GetMapBlockWidth();
			 tile_dimensions.y = GetMapBlockHeight();
            
            
                           
		ChangeMapLayer(1);
      
			player.Reset(); //player spawn and reset vars
			//enemy_spawn(); //Enemy spawns 
               
        ChangeMapLayer(0);  
       // MappyLevel.SetMapDimensions(App::getInstance().Get_RenderWindow()->GetWidth(), App::getInstance().Get_RenderWindow()->GetHeight());
      
		//checkpoint.save_position(player.px, player.py, x_start, y_start); //clear checkpoints
      
      }//end ov real map    

	  SetMapDimensions(Get_PixelSize().x, Get_PixelSize().y);
	  GenerateMapYLookup();
}//End ov function





/* Load Map via Number */
/***********************/
void c_Map::Load(int mapNum)
{
     Set_Current(mapNum);
     Load();
}


/* Load Next Map */
/*****************/
void c_Map::Load_Next()
{
     current_map++;
     Load();
}


/* Load Previous Map */
void c_Map::Load_Previous()
{
     current_map--;
     Load();
}




/* Reset current Map */
/*********************/
void c_Map::Reset()
{
	//Reset backgrounds
	for(int i = 0; i < Backgrounds.size(); i++)
	{
		Backgrounds[i].Reset();
	}

	/*
     screen_fade_out(15);
     
     player.state = ground;
     player.px = checkpoint.set_x();
     player.py = checkpoint.set_y();
     
     player.x_vel = 0;
     player.y_vel = 0;
     
     x_scroll = checkpoint.set_scroll_x();
     y_scroll = checkpoint.set_scroll_y();
	 */
}//end ov function




//Update logic for map
void c_Map::Update_Logic()
{
	//update maps animations
	 UpdateMapAnims();


	 //Update Gravity
	 Map.gravity = Map.savedGravity * App::getInstance().Get_RenderWindow()->GetFrameTime();

//UPdate Background logic
	 for(int i = 0; i < Backgrounds.size(); i++)
	 {
		 Backgrounds[i].Update_Logic();
	 }
	 
}//EoF


/* Draw Map with unique layer */
/******************************/
void c_Map::Draw(int layer)
{
//blit the Background
	  //Change_Layers(0);

	
	
      switch(layer)
      {
                   case 0:
					   for(int i = 0; i < Backgrounds.size(); i++)
					   {
								Backgrounds[i].Draw();
					   }
					    
                     //  blit(Images.background, get_buffer(), 0, 0, 0, 0, Images.background->w, Images.background->h);
                        
					    DrawMapBG (*App::getInstance().Get_RenderWindow(),  Cam.Get_Camera().x,  Cam.Get_Camera().y, 0, 0, App::getInstance().Get_RenderWindow()->GetWidth(), App::getInstance().Get_RenderWindow()->GetHeight() );     //Draw background later   
                       
                        break;
                        
                   default:
                           
                        DrawMapFG(*App::getInstance().Get_RenderWindow(),  Cam.Get_Camera().x,  Cam.Get_Camera().y, 0, 0, App::getInstance().Get_RenderWindow()->GetWidth(), App::getInstance().Get_RenderWindow()->GetHeight() , layer-1);     //Draw foreground later
      }//end ov switch  
	  
}//End ov function



void c_Map::Destroy()
{
              // MappyLevel.FreeMapMem();
}


//Change layers
void c_Map::Change_Layers(const int layer)
{
	ChangeMapLayer(layer);
}









